package cn.ynrcb.personnelfile.sysadmin.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.ynrcb.personnelfile.admin.enums.SmsTypeEnum;
import cn.ynrcb.personnelfile.admin.service.SmsService;
import cn.ynrcb.personnelfile.admin.vo.SmsVo;
import cn.ynrcb.personnelfile.common.annotation.SysLog;
import cn.ynrcb.personnelfile.common.exception.MyException;
import cn.ynrcb.personnelfile.common.utils.PageUtils;
import cn.ynrcb.personnelfile.common.utils.R;
import cn.ynrcb.personnelfile.common.validator.Assert;
import cn.ynrcb.personnelfile.common.validator.ValidatorUtils;
import cn.ynrcb.personnelfile.common.validator.group.AddGroup;
import cn.ynrcb.personnelfile.sysadmin.dao.SysUserDao;
import cn.ynrcb.personnelfile.sysadmin.entity.SysDictEntity;
import cn.ynrcb.personnelfile.sysadmin.entity.SysUserEntity;
import cn.ynrcb.personnelfile.sysadmin.form.PasswordForm;
import cn.ynrcb.personnelfile.sysadmin.service.SysCaptchaService;
import cn.ynrcb.personnelfile.sysadmin.service.SysDictService;
import cn.ynrcb.personnelfile.sysadmin.service.SysUserRoleService;
import cn.ynrcb.personnelfile.sysadmin.service.SysUserService;
import cn.ynrcb.personnelfile.sysadmin.vo.UserVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.credential.DefaultPasswordService;
import org.apache.shiro.authc.credential.PasswordService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 系统用户
 */
@Slf4j
@RestController
@Api(value = "整改需求系统系统",tags = {"系统相关=>用户相关接口"})
@RequestMapping("/sys/user")
public class SysUserController extends AbstractController {
	@Autowired
	private SysUserService sysUserService;
	@Autowired
	private SysUserDao sysUserDao;
	@Autowired
	private SysUserRoleService sysUserRoleService;
	@Autowired
	private SysCaptchaService sysCaptchaService;
	@Autowired
	private SmsService smsService;
	@Autowired
	private SysDictService sysDictService;

	/**
	 * 监测注册驳回手机号
	 */
	@ApiOperation("监测注册驳回手机号")
	@ApiOperationSupport(
			responses = @DynamicResponseParameters(properties = {
					@DynamicParameter(value = "状态码",name = "code",example = "0"),
					@DynamicParameter(value = "信息",name = "msg",example = "匹配成功")
			})
	)
	@GetMapping("/nopassmobile")
	public R nopassmobile(@RequestParam Map<String, Object> params){
		String mobile = Convert.toStr(params.get("mobile"));
		String uuid = Convert.toStr(params.get("uuid"));
		String captchaStr = Convert.toStr(params.get("captcha"));
		//验证验证码
		boolean captcha = sysCaptchaService.validate(uuid, captchaStr);
		if(!captcha){
			return R.error(2001,"验证码不正确！");
		}

		if(!cn.ynrcb.personnelfile.common.utils.ValidatorUtils.isMobile(mobile)){
			return R.error("手机号格式不正确！");
		}
		SysUserEntity user = sysUserDao.getNoPassUserByMobile(mobile);
		if(!user.getMobile().equals(mobile) || ObjectUtil.isNull(user)){
			return R.error("该手机号没有驳回注册用户！");
		}
		return R.ok("匹配成功").put("user",user);
	}

	/**
	 * 监测旧手机号是否与当前用户匹配
	 */
	@ApiOperation("监测旧手机号是否与当前用户匹配")
	@ApiOperationSupport(
			responses = @DynamicResponseParameters(properties = {
					@DynamicParameter(value = "状态码",name = "code",example = "0"),
					@DynamicParameter(value = "信息",name = "msg",example = "匹配成功")
			})
	)
	@GetMapping("/oldMobile/{oldMobile}")
	@RequiresPermissions("sys:user:oldMobile")
	public R oldMobile(@PathVariable("oldMobile") String oldMobile){
		if(!cn.ynrcb.personnelfile.common.utils.ValidatorUtils.isMobile(oldMobile)){
			return R.error("手机号格式不正确！");
		}
		if(!getUser().getMobile().equals(oldMobile)){
			return R.error("旧手机号不匹配");
		}
		return R.ok("匹配成功");
	}

	/**
	 * 绑定手机
	 */
	@ApiOperation("绑定手机")
	@ApiOperationSupport(
			responses = @DynamicResponseParameters(properties = {
					@DynamicParameter(value = "状态码",name = "code",example = "0"),
					@DynamicParameter(value = "信息",name = "msg",example = "绑定成功")
			})
	)
	@ApiResponses({
			@ApiResponse(code = 2001,message = "验证码不正确！"),
			@ApiResponse(code = 2012,message = "短信验证码不正确！"),
			@ApiResponse(code = 2013,message = "该手机号已绑定其他用户！")
	})
	@SysLog("绑定手机")
	@PostMapping("/bind")
	@RequiresPermissions("sys:user:bind")
	public R bindMobile(@RequestBody UserVo.UserBindParams params){
		ValidatorUtils.validateEntity(params, AddGroup.class);
//		//验证验证码
//		boolean captcha = sysCaptchaService.validate(params.getUuid(), params.getCaptcha());
//		if(!captcha){
//			return R.error(2001,"验证码不正确！");
//		}
		//验证号码是否重复
		SysUserEntity user = sysUserService.getOne(new QueryWrapper<SysUserEntity>().eq("mobile",params.getMobile()).ne("status",-1));
		if(ObjectUtil.isNotNull(user)) return R.error(2013, params.getMobile() + ",该手机号已绑定其他用户!");

		//验证短信验证码
		SmsVo.CheckSmsParm param = new SmsVo.CheckSmsParm();
		param.setPhone(params.getMobile());
		param.setSmsCode(params.getSmsCode());
		param.setType(SmsTypeEnum.BIND_MOBILE);

		if(!smsService.checkSmsCode(param)) {
			return R.error(2012, "短信验证码不正确或已过期！");
		}
		sysUserService.bindMobileAndEmail(params);
		return R.ok("修改密码成功");

	}

	/**
	 * 更换绑定手机
	 */
	@ApiOperation("更换绑定手机")
	@ApiOperationSupport(
			responses = @DynamicResponseParameters(properties = {
					@DynamicParameter(value = "状态码",name = "code",example = "0"),
					@DynamicParameter(value = "信息",name = "msg",example = "绑定成功")
			})
	)
	@ApiResponses({
			@ApiResponse(code = 2001,message = "验证码不正确！"),
			@ApiResponse(code = 2012,message = "短信验证码不正确！"),
			@ApiResponse(code = 2013,message = "该手机号已绑定其他用户！")
	})
	@SysLog("更换绑定手机")
	@PostMapping("/replaceBind")
	@RequiresPermissions("sys:user:replaceBind")
	public R replaceBind(@RequestBody UserVo.UserReplaceBindParams params){
		ValidatorUtils.validateEntity(params, AddGroup.class);
//		//验证验证码
//		boolean captcha = sysCaptchaService.validate(params.getUuid(), params.getCaptcha());
//		if(!captcha){
//			return R.error(2001,"验证码不正确！");
//		}
		//验证号码是否重复
		SysUserEntity user = sysUserService.getOne(new QueryWrapper<SysUserEntity>().eq("mobile",params.getMobile()).ne("status",-1));
		if(ObjectUtil.isNull(user)){
			//与其他用户号码不重复时，查找用户名是否与该号码重复
			user = sysUserService.getOne(new QueryWrapper<SysUserEntity>().eq("username",params.getMobile()).ne("status",-1));
		}
		if(ObjectUtil.isNotNull(user)) return R.error(2013, params.getMobile() + ",该手机号已绑定其他用户!");

		//验证旧手机短信验证码
		SmsVo.CheckSmsParm param = new SmsVo.CheckSmsParm();
		param.setPhone(params.getOldMobile());
		param.setSmsCode(params.getOldSmsCode());
		param.setType(SmsTypeEnum.REPLACE_MOBILE);

		if(!smsService.checkSmsCode(param)) {
			return R.error(2012, "旧手机短信验证码不正确或已过期！");
		}

		//验证新手机短信验证码
		param.setPhone(params.getMobile());
		param.setSmsCode(params.getSmsCode());
		param.setType(SmsTypeEnum.REPLACE_MOBILE);

		if(!smsService.checkSmsCode(param)) {
			return R.error(2012, "新手机短信验证码不正确或已过期！");
		}

		sysUserService.replaceBind(params);
		return R.ok("修改绑定手机成功");

	}

	/**
	 * 待审核用户分页查询
	 */
	@ApiOperation("待审核用户分页查询")
	@GetMapping("/listaudit")
	@RequiresPermissions("sys:user:listaudit")
	public R listAudit(@RequestParam Map<String, Object> params){
		PageUtils page = sysUserService.queryAuditPage(params);
		return R.ok().put("page", page);
	}

	/**
	 * 机构用户分页查询
	 */
	@ApiOperation("机构用户分页查询")
	@GetMapping("/listAdmin")
	@RequiresPermissions("sys:user:listAdmin")
	public R listAdmin(@RequestParam Map<String, Object> params){
		PageUtils page = sysUserService.queryPageAdmin(params);
		return R.ok().put("page", page);
	}

	/**
	 * 修改用户锁定状态-锁定/解锁
	 */
	@ApiOperation("修改用户锁定状态-锁定/解锁")
	@ApiOperationSupport(
			responses = @DynamicResponseParameters(properties = {
					@DynamicParameter(value = "状态码",name = "code",example = "0"),
					@DynamicParameter(value = "信息",name = "msg",example = "修改成功！")
			})
	)
	@SysLog("修改用户锁定状态-锁定/解锁")
	@GetMapping("/lock/{userId}")
	@RequiresPermissions("sys:user:lock")
	public R lockState(@PathVariable("userId") Long userId){
		if(getUser().getRoleId() == 1 || sysUserService.getById(userId).getRoleId() > getUser().getRoleId()){
			sysUserService.lockState(userId);
			return R.ok("修改成功！");
		}
		return R.error("不可越级操作！");
	}

	/**
	 * 修改用户状态-禁用/启用
	 */
	@ApiOperation("修改用户状态-禁用/启用")
	@ApiOperationSupport(
			responses = @DynamicResponseParameters(properties = {
					@DynamicParameter(value = "状态码",name = "code",example = "0"),
					@DynamicParameter(value = "信息",name = "msg",example = "修改成功！")
			})
	)
	@SysLog("修改用户状态-禁用/启用")
	@GetMapping("/switch/{userId}")
	@RequiresPermissions("sys:user:switch")
	public R switchState(@PathVariable("userId") Long userId){
		if(getUser().getRoleId() == 1 || sysUserService.getById(userId).getRoleId() > getUser().getRoleId()){
			sysUserService.switchState(userId);
			return R.ok("修改成功！");
		}
		return R.error("不可越级操作！");
	}

	/**
	 * 注册协会用户
	 */
	@ApiOperation("注册协会用户")
	@ApiOperationSupport(
			responses = @DynamicResponseParameters(properties = {
					@DynamicParameter(value = "状态码",name = "code",example = "0"),
					@DynamicParameter(value = "信息",name = "msg",example = "注册成功")
			})
	)
	@ApiResponses({
			@ApiResponse(code = 2001,message = "验证码不正确或已过期！"),
			@ApiResponse(code = 2012,message = "短信验证码不正确！")
	})
	@SysLog("注册用户")
	@PostMapping("/register")
	public R register(@RequestBody UserVo.UserRegisterParams params){
		ValidatorUtils.validateEntity(params, AddGroup.class);
		//验证短信验证码
		SmsVo.CheckSmsParm param = new SmsVo.CheckSmsParm();
		param.setPhone(params.getMobile());
		param.setSmsCode(params.getSmsCode());
		param.setType(SmsTypeEnum.BIND_MOBILE);

		if(!smsService.checkSmsCode(param)) {
			return R.error(2012, "短信验证码不正确或已过期！");
		}
		//校验社会信用代码格式
		if(!cn.ynrcb.personnelfile.common.utils.ValidatorUtils.isCredictCode(params.getCreditCode())){
			return R.error(2014,"社会信用代码格式错误！");
		}
		sysUserService.userRegister(params);

		return R.ok("注册成功");
	}

	/**
	 * 忘记密码
	 */
	@ApiOperation("忘记密码")
	@ApiOperationSupport(
			responses = @DynamicResponseParameters(properties = {
					@DynamicParameter(value = "状态码",name = "code",example = "0"),
					@DynamicParameter(value = "信息",name = "msg",example = "修改密码成功")
			})
	)
	@ApiResponses({
			@ApiResponse(code = 2001,message = "验证码不正确！"),
			@ApiResponse(code = 2012,message = "短信验证码不正确！")
	})
	@SysLog("忘记密码")
	@PostMapping("/forgetPsw")
	public R forget(@RequestBody UserVo.UserForgetParams params){
		ValidatorUtils.validateEntity(params, AddGroup.class);
//		//验证验证码
//		boolean captcha = sysCaptchaService.validate(params.getUuid(), params.getCaptcha());
//		if(!captcha){
//			return R.error(2001,"验证码不正确！");
//		}
		//验证短信验证码
		SmsVo.CheckSmsParm param = new SmsVo.CheckSmsParm();
		param.setPhone(params.getMobile());
		param.setSmsCode(params.getSmsCode());
		param.setType(SmsTypeEnum.PSW_RESET);

		if(!smsService.checkSmsCode(param)) {
			return R.error(2012, "短信验证码不正确或已过期！");
		}

		if(sysUserService.forgetPassword(params)){
			return R.ok("修改密码成功");
		}else{
			return R.error("修改密码失败！请联系管理员");
		}
	}

	/**
	 * 获取登录的用户信息
	 */
	@GetMapping("/info")
	public R info(){
		UserVo.UserLoginVo loginUser = sysUserDao.queryByUserName(getUser().getUsername());
		loginUser.setSalt("");
		loginUser.setPassword("");
		return R.ok().put("user",loginUser);
	}
	
	/**
	 * 修改登录用户密码
	 */
	@SysLog("修改密码")
	@PostMapping("/password")
	public R password(@RequestBody PasswordForm form){
		Assert.isBlank(form.getNewPassword(), "新密码不为能空");
		//验证密码规则
		if(!cn.ynrcb.personnelfile.common.utils.ValidatorUtils.checkPasswordRule(form.getNewPassword())){
			throw new MyException("该密码不符合规则！");
		}
		boolean flag = false;
		if (StringUtils.isNotBlank(getUser().getSalt())){
			//盐值不为空，新系统用户
			//sha256加密
			String password = new Sha256Hash(form.getPassword(), getUser().getSalt()).toHex();
			//sha256加密
			String newPassword = new Sha256Hash(form.getNewPassword(), getUser().getSalt()).toHex();

			//更新密码
			flag = sysUserService.updatePassword(getUserId(), password, newPassword);
			if(!flag){
				return R.error("原密码不正确");
			}
		}else{
			//盐值为空，老系统用户
			PasswordService svc = new DefaultPasswordService();
			flag = svc.passwordsMatch(form.getPassword(),getUser().getPassword());
			if(!flag){
				return R.error("原密码不正确");
			}
			//sha256加密
			String salt = RandomStringUtils.randomAlphanumeric(20);
			form.setNewPassword(new Sha256Hash(form.getNewPassword(), salt).toHex()); //密码加密
			SysUserEntity userEntity = sysUserService.getById(getUserId());
			userEntity.setSalt(salt);
			userEntity.setPassword(form.getNewPassword());
			sysUserService.updateById(userEntity);
		}
		return R.ok();
	}

	/**
	 * 根据userId来获取用户信息
	 */
	@ApiOperation("根据userId来获取用户信息")
	@ApiImplicitParam(name = "userId", value = "用户ID",example ="2", required = true)
	@ApiOperationSupport(
			responses = @DynamicResponseParameters(properties = {
					@DynamicParameter(value = "状态码",name = "code",example = "0"),
					@DynamicParameter(value = "信息",name = "msg",example = "修改密码成功"),
					@DynamicParameter(value = "用户信息",name = "user",dataTypeClass = SysUserEntity.class)
			})
	)
	@GetMapping("/info/{userId}")
	@RequiresPermissions("sys:user:info")
	public R info(@PathVariable("userId") Long userId){
		SysUserEntity user = sysUserService.getById(userId);

		//获取用户所属的角色列表
		List<Integer> roleIdList = sysUserRoleService.queryRoleIdList(userId);
		user.setRoleIdList(roleIdList);

		return R.ok().put("user", user);
	}

	/**
	 * 保存用户
	 */
	@SysLog("保存用户")
	@PostMapping("/save")
	@RequiresPermissions("sys:user:save")
	public R save(@RequestBody SysUserEntity user){
		user.setCreateUserId(getUserId());
		sysUserService.saveUser(user);

		return R.ok();
	}

	/**
	 * 修改用户
	 */
	@SysLog("修改用户")
	@PostMapping("/update")
	@RequiresPermissions("sys:user:update")
	public R update(@RequestBody SysUserEntity user){
//		ValidatorUtils.validateEntity(user, UpdateGroup.class);  //hibernate的validate冲突了
		if(getUser().getRoleId() == 1 || sysUserService.getById(user.getUserId()).getRoleId() > getUser().getRoleId() || getUserId() == user.getUserId()) {
			user.setUpdateUserId(getCurrentUserId());
			user.setUpdateTime(new Date());
			sysUserService.update(user, 2);//2不为绑定按钮
			return R.ok();
		}
		return R.error("不可越级操作！");
	}

	/**
	 * 删除用户
	 */
	@SysLog("删除用户")
	@PostMapping("/delete")
	@RequiresPermissions("sys:user:delete")
	public R delete(@RequestBody Long[] userIds){
		if(ArrayUtils.contains(userIds, 1L)){
			return R.error("系统管理员不能删除");
		}

		if(ArrayUtils.contains(userIds, getUserId())){
			return R.error("当前用户不能删除");
		}

		sysUserService.deleteBatch(userIds);
		//删除用户表和角色中间表的数据
		sysUserRoleService.deleteByUserId(Arrays.asList(userIds));

		return R.ok();
	}

	/**
	 * 重置密码
	 */
	@SysLog("重置密码")
	@GetMapping("/resetPassword")
	@RequiresPermissions("sys:user:resetpassword")
	public R resetPassword(Long userId){
		//读取数据库中的默认密码
		SysDictEntity dict = sysDictService.getOne(
				new QueryWrapper<SysDictEntity>()
						.eq("type","password")
						.eq("label","password")
		);
		sysUserService.resetPassword(userId,dict.getValue());
		return R.ok();
	}

	/**
	 * 系统用户分页查询
	 */
	@ApiOperation("系统用户分页查询")
	@ApiImplicitParam(name="params", value="分页数据page和limit", required = true)
	@GetMapping("/sysList")
//	@RequiresPermissions("sys:user:sysList")
	public R sysList(@RequestParam Map<String, Object> params){
//		//只有超级管理员，才能查看所有管理员列表
//		if(getUserId() != Constant.SUPER_ADMIN){
//			params.put("createUserId", getUserId());
//			params.put("innerCode", getInnerCode());
//		}
		PageUtils page = sysUserService.querySysPage(params);
		return R.ok().put("page", page);
	}


}
